package com.journey.org.app

import android.content.Intent
import android.util.MalformedJsonException
import androidx.lifecycle.LifecycleOwner
import com.google.gson.JsonParseException
import com.journey.org.JourneyApplication
import com.journey.org.ui.login.LoginActivity
import com.mvvmhabit.org.BaseApplication
import com.mvvmhabit.org.http.CoroutineLifecycleListener
import com.mvvmhabit.org.http.ResponseThrowable
import com.mvvmhabit.org.utils.NetworkUtil
import com.mvvmhabit.org.utils.ToastUtils
import kotlinx.coroutines.*
import org.apache.http.conn.ConnectTimeoutException
import org.json.JSONException
import retrofit2.HttpException
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
import java.text.ParseException
import javax.net.ssl.SSLException

// 玩安卓相关内容
class RequestPlayAndroid<T> {

    private val UNAUTHORIZED: Int = 401

    private val BAD_REQUEST: Int = 400

    private val FORBIDDEN: Int = 403

    private val NOT_FOUND: Int = 404

    private val REQUEST_TIMEOUT: Int = 408

    private val INTERNAL_SERVER_ERROR: Int = 500

    private val SERVICE_UNAVAILABLE: Int = 503

    lateinit var loader: suspend () -> PlayAndroidResponse<T>

    var start: (() -> Unit)? = null

    var onSuccess: ((T) -> Unit)? = null

    var onError: ((ResponseThrowable) -> Unit)? = null

    var onComplete: (() -> Unit)? = null

    var addLifecycle: LifecycleOwner? = null

    infix fun onLoader(loader: suspend () -> PlayAndroidResponse<T>) {
        this.loader = loader
    }

    infix fun onStart(start: (() -> Unit)?) {
        this.start = start
    }

    infix fun onSuccess(onSuccess: ((T) -> Unit)?) {
        this.onSuccess = onSuccess
    }

    infix fun onError(onError: ((ResponseThrowable) -> Unit)?) {
        this.onError = onError
    }

    infix fun onComplete(onComplete: (() -> Unit)?) {
        this.onComplete = onComplete
    }

    infix fun addLifecycle(addLifecycle: LifecycleOwner?) {
        this.addLifecycle = addLifecycle
    }

    fun request() {
        request(addLifecycle)
    }


    fun request(addLifecycle: LifecycleOwner?) {

        GlobalScope.launch(context = Dispatchers.Main) {
            start?.invoke()
            try {
                val deferred = GlobalScope.async(Dispatchers.IO, start = CoroutineStart.LAZY) {
                    loader()
                }
                addLifecycle?.apply {
                    lifecycle.addObserver(
                        CoroutineLifecycleListener(
                            deferred,
                            lifecycle
                        )
                    )
                }
                val result = deferred.await()
                if (result.errorCode == 0) {
                    onSuccess?.invoke(result.data!!)
                } else {
                    ToastUtils.showShort(result.errorMsg)
                    onError?.invoke(
                        ResponseThrowable(
                            Throwable(result.errorMsg),
                            result.errorCode
                        )
                    )
                }
            } catch (e: Exception) {
                e.printStackTrace()
                val ex: ResponseThrowable
                if (e is HttpException) {
                    ex = ResponseThrowable(e, 1003)
                    ex.message = "未知错误"
                    when (e.code()) {
                        UNAUTHORIZED -> {
                            ex.message = "操作未授权"
                            GlobalScope.launch(Dispatchers.IO) {
                                requestHttpManager {
                                    loader()
                                }
                            }
                        }
                        BAD_REQUEST -> {
                            ex.message = "请求错误"
                            GlobalScope.launch(Dispatchers.IO) {
                                requestHttpManager {
                                    request()
                                }
                            }
                        }

                        FORBIDDEN -> {
                            ex.message = "请求被拒绝"
                        }
                        NOT_FOUND -> {
                            ex.message = "资源不存在"
                        }
                        REQUEST_TIMEOUT -> {
                            ex.message = "服务器执行超时"
                        }
                        INTERNAL_SERVER_ERROR -> {
                            ex.message = "服务器内部错误"
                        }
                        SERVICE_UNAVAILABLE -> {
                            ex.message = "服务器不可用"
                        }
                    }
                } else if (e is JsonParseException || e is JSONException || e is ParseException || e is MalformedJsonException) {
                    ex = ResponseThrowable(e, 1001)
                    ex.message = "解析错误"
                } else if (e is ConnectException) {
                    ex = ResponseThrowable(e, 1002)
                    ex.message = "连接失败"
                } else if (e is SSLException) {
                    ex = ResponseThrowable(e, 1005)
                    ex.message = "证书验证失败"
                } else if (e is ConnectTimeoutException) {
                    ex = ResponseThrowable(e, 1006)
                    ex.message = "连接超时"
                } else if (e is SocketTimeoutException) {
                    ex = ResponseThrowable(e, 1006)
                    ex.message = "连接超时"
                } else if (e is UnknownHostException) {
                    ex = ResponseThrowable(e, 1006)
                    ex.message = "主机地址未知"
                } else {
                    ex = ResponseThrowable(e, 1000)
                    ex.message = "未知错误"
                }
                ToastUtils.showShort(ex.message)
                onError?.invoke(ex)
            } finally {
                onComplete?.invoke()
            }
        }
    }
}


class RequestBaoBase<T> {

    private val UNAUTHORIZED: Int = 401

    private val BAD_REQUEST: Int = 400

    private val FORBIDDEN: Int = 403

    private val NOT_FOUND: Int = 404

    private val REQUEST_TIMEOUT: Int = 408

    private val INTERNAL_SERVER_ERROR: Int = 500

    private val SERVICE_UNAVAILABLE: Int = 503

    lateinit var loader: suspend () -> BaoBaBaseResponse<T>

    var start: (() -> Unit)? = null

    var onSuccess: ((T) -> Unit)? = null

    var onError: ((ResponseThrowable) -> Unit)? = null

    var onComplete: (() -> Unit)? = null

    var addLifecycle: LifecycleOwner? = null

    infix fun onLoader(loader: suspend () -> BaoBaBaseResponse<T>) {
        this.loader = loader
    }

    infix fun onStart(start: (() -> Unit)?) {
        this.start = start
    }

    infix fun onSuccess(onSuccess: ((T) -> Unit)?) {
        this.onSuccess = onSuccess
    }

    infix fun onError(onError: ((ResponseThrowable) -> Unit)?) {
        this.onError = onError
    }

    infix fun onComplete(onComplete: (() -> Unit)?) {
        this.onComplete = onComplete
    }

    infix fun addLifecycle(addLifecycle: LifecycleOwner?) {
        this.addLifecycle = addLifecycle
    }

    fun request() {
        request(addLifecycle)
    }


    fun request(addLifecycle: LifecycleOwner?) {

        GlobalScope.launch(context = Dispatchers.Main) {

            start?.invoke()
            try {
                val deferred = GlobalScope.async(Dispatchers.IO, start = CoroutineStart.LAZY) {
                    loader()
                }
                addLifecycle?.apply {
                    lifecycle.addObserver(
                        CoroutineLifecycleListener(
                            deferred,
                            lifecycle
                        )
                    )
                }
                val result = deferred.await()
                if (result.itemList != null) {
                    onSuccess?.invoke(result.itemList!!)
                } else {
                    ToastUtils.showShort("暂无数据！")
                    onError?.invoke(
                        ResponseThrowable(
                            Throwable("暂无数据！"),
                            400
                        )
                    )
                }

            } catch (e: Exception) {
                e.printStackTrace()
                val ex: ResponseThrowable
                if (e is HttpException) {
                    ex = ResponseThrowable(e, 1003)
                    ex.message = "未知错误"
                    when (e.code()) {
                        UNAUTHORIZED -> {
                            ex.message = "操作未授权"
                            GlobalScope.launch(Dispatchers.IO) {
                                requestHttpManager {
                                    loader()
                                }
                            }
                        }
                        BAD_REQUEST -> {
                            ex.message = "请求错误"
                            GlobalScope.launch(Dispatchers.IO) {
                                requestHttpManager {
                                    request()
                                }
                            }
                        }

                        FORBIDDEN -> {
                            ex.message = "请求被拒绝"
                        }
                        NOT_FOUND -> {
                            ex.message = "资源不存在"
                        }
                        REQUEST_TIMEOUT -> {
                            ex.message = "服务器执行超时"
                        }
                        INTERNAL_SERVER_ERROR -> {
                            ex.message = "服务器内部错误"
                        }
                        SERVICE_UNAVAILABLE -> {
                            ex.message = "服务器不可用"
                        }
                    }
                } else if (e is JsonParseException || e is JSONException || e is ParseException || e is MalformedJsonException) {
                    ex = ResponseThrowable(e, 1001)
                    ex.message = "解析错误"
                } else if (e is ConnectException) {
                    ex = ResponseThrowable(e, 1002)
                    ex.message = "连接失败"
                } else if (e is SSLException) {
                    ex = ResponseThrowable(e, 1005)
                    ex.message = "证书验证失败"
                } else if (e is ConnectTimeoutException) {
                    ex = ResponseThrowable(e, 1006)
                    ex.message = "连接超时"
                } else if (e is SocketTimeoutException) {
                    ex = ResponseThrowable(e, 1006)
                    ex.message = "连接超时"
                } else if (e is UnknownHostException) {
                    ex = ResponseThrowable(e, 1006)
                    ex.message = "主机地址未知"
                } else {
                    ex = ResponseThrowable(e, 1000)
                    ex.message = "未知错误"
                }
                ToastUtils.showShort(ex.message)
                onError?.invoke(ex)
            } finally {
                onComplete?.invoke()
            }
        }
    }
}


class RequestBase<T> {
    private lateinit var loader: suspend () -> BaseResponse<T>

    private var start: (() -> Unit)? = null

    private var onSuccess: ((T) -> Unit)? = null

    private var onError: ((ResponseThrowable) -> Unit)? = null

    private var onComplete: (() -> Unit)? = null

    private var addLifecycle: LifecycleOwner? = null

    private val UNAUTHORIZED: Int = 401

    private val BAD_REQUEST: Int = 400

    private val FORBIDDEN: Int = 403

    private val NOT_FOUND: Int = 404

    private val REQUEST_TIMEOUT: Int = 408

    private val INTERNAL_SERVER_ERROR: Int = 500

    private val SERVICE_UNAVAILABLE: Int = 503


    infix fun onLoader(loader: suspend () -> BaseResponse<T>) {
        this.loader = loader
    }

    infix fun onStart(start: (() -> Unit)?) {
        this.start = start
    }

    infix fun onSuccess(onSuccess: ((T) -> Unit)?) {
        this.onSuccess = onSuccess
    }

    infix fun onError(onError: ((ResponseThrowable) -> Unit)?) {
        this.onError = onError
    }

    infix fun onComplete(onComplete: (() -> Unit)?) {
        this.onComplete = onComplete
    }

    infix fun addLifecycle(addLifecycle: LifecycleOwner?) {
        this.addLifecycle = addLifecycle
    }

    fun request() {
        request(addLifecycle)
    }

    fun request(addLifecycle: LifecycleOwner?) {
        GlobalScope.launch(context = Dispatchers.Main) {
            val isNetwork = NetworkUtil.isNetworkAvailable(BaseApplication.getInstance())
            if (!isNetwork) { // 暂无网络
                onError?.invoke(
                    ResponseThrowable(
                        Throwable("网络不可用!"),
                        500
                    )
                )
                ToastUtils.showShort("网络不可用!")
                return@launch
            }
            start?.invoke()
            try {
                val deferred = GlobalScope.async(
                    Dispatchers.IO, start = CoroutineStart.LAZY
                ) {
                    loader()
                }
                addLifecycle?.apply {
                    lifecycle.addObserver(
                        CoroutineLifecycleListener(
                            deferred,
                            lifecycle
                        )
                    )
                }
                val result = deferred.await()
                if (result.code == "0" || result.code == "200") { // 成功内容
                    onSuccess?.invoke(result.data!!)
                } else if (result.code == "A230") { // token过期
                    // 跳转到登录界面
                    startLoginActivity()
                } else { // 错误
                    ToastUtils.showShort(result.msg)
                    onError?.invoke(
                        ResponseThrowable(
                            Throwable(result.msg),
                            result.code.toInt()
                        )
                    )
                }
            } catch (e: Exception) {
                e.printStackTrace()
                val ex: ResponseThrowable
                if (e is HttpException) {
                    ex = ResponseThrowable(e, 1003)
                    ex.message = "未知错误"
                    when (e.code()) {
                        UNAUTHORIZED -> {
                            ex.message = "操作未授权"
                            // 跳转到登录界面
                            startLoginActivity()
                        }
                        BAD_REQUEST -> {
                            ex.message = "请求错误"
                            GlobalScope.launch(Dispatchers.IO) {
                                requestHttpManager {
//                                    val isTimeout = loginTimeout()
//                                    if (isTimeout) {
//                                        request()
//                                    }
                                    request()
                                }
                            }
                        }

                        FORBIDDEN -> {
                            ex.message = "请求被拒绝"
                        }
                        NOT_FOUND -> {
                            ex.message = "资源不存在"
                        }
                        REQUEST_TIMEOUT -> {
                            ex.message = "服务器执行超时"
                        }
                        INTERNAL_SERVER_ERROR -> {
                            ex.message = "服务器内部错误"
                        }
                        SERVICE_UNAVAILABLE -> {
                            ex.message = "服务器不可用"
                        }
                    }
                } else if (e is JsonParseException || e is JSONException || e is ParseException || e is MalformedJsonException) {
                    ex = ResponseThrowable(e, 1001)
                    ex.message = "解析错误"
                } else if (e is ConnectException) {
                    ex = ResponseThrowable(e, 1002)
                    ex.message = "连接失败"
                } else if (e is SSLException) {
                    ex = ResponseThrowable(e, 1005)
                    ex.message = "证书验证失败"
                } else if (e is ConnectTimeoutException) {
                    ex = ResponseThrowable(e, 1006)
                    ex.message = "连接超时"
                } else if (e is SocketTimeoutException) {
                    ex = ResponseThrowable(e, 1006)
                    ex.message = "连接超时"
                } else if (e is UnknownHostException) {
                    ex = ResponseThrowable(e, 1006)
                    ex.message = "主机地址未知"
                } else {
                    ex = ResponseThrowable(e, 1000)
                    ex.message = "未知错误"
                }
                ToastUtils.showShort(ex.message)
                onError?.invoke(ex)
            } finally {
                onComplete?.invoke()
            }
        }
    }

    /**
     * 跳转到登录界面
     */
    private fun startLoginActivity() {
        val intent = Intent()
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
        intent.setClass(
            BaseApplication.getInstance()?.applicationContext!!,
            LoginActivity::class.java
        )
        BaseApplication.getInstance()?.applicationContext!!.startActivity(intent)
    }
}

inline fun <T> requestBase(buildRequest: RequestBase<T>.() -> Unit) {
    RequestBase<T>().apply(buildRequest).request()
}

inline fun <T> LifecycleOwner.requestBase(buildRequest: RequestBase<T>.() -> Unit) {
    RequestBase<T>().apply(buildRequest).request(this)
}

inline fun <T> requestPlayAndroid(buildRequest: RequestPlayAndroid<T>.() -> Unit) {
    RequestPlayAndroid<T>().apply(buildRequest).request()
}

inline fun <T> LifecycleOwner.requestPlayAndroid(buildRequest: RequestPlayAndroid<T>.() -> Unit) {
    RequestPlayAndroid<T>().apply(buildRequest).request(this)
}


inline fun <T> requestBaoBase(buildRequest: RequestBaoBase<T>.() -> Unit) {
    RequestBaoBase<T>().apply(buildRequest).request()
}

inline fun <T> LifecycleOwner.requestBaoBase(buildRequest: RequestBaoBase<T>.() -> Unit) {
    RequestBaoBase<T>().apply(buildRequest).request(this)
}